<?php
/**
 * 图片处理类
 *
 * <code>
 *     $i = new Image('/tmp/a.png');
 *     $i->addWatermark('/tmp/w.png', 10, 10);
 *     $i->addText('hello world!');
 *     $i->thumb(150, 150);
 *     $i->save('/tmp/a.png');
 * </code>
 *
 */

class Image {

    protected $_image;
    protected $_imageHandle;

    protected $_type;
    protected $_width;
    protected $_height;

    /**
     * __construct
     * 载入图片
     * 
     * @param  string $image 图片文件地址
     * @trhows Image_Exception
     * @return boolean
     */
    public function __construct($image) {
        if (!$image || !is_file($image)) {
            throw new Image_Exception('Image is not exist');
        }
        $this->_image = $image;

        list($this->_width, $this->_height, $this->_type) = $this->_getInfo($image);
        if (!$this->_isSupportType($this->_type)) {
            throw new Image_Exception('Unexpect Image type');
        }

        $this->_imageHandle = $this->_createImageHandle($image, $this->_type);
        if (!$this->_imageHandle) {
            throw new Image_Exception('Can not load image');
        }

        return true;
    }

    /**
     * addText
     * 添加文字
     * 
     * @param  string $text 文字
     * @param  string $text 文字
     * @param  string $size 大小
     * @param  string $x X坐标
     * @param  string $y Y坐标
     * @param  string $color 颜色(十六进制或颜色名称，例如#000000、black)
     * @param  string $angle 角度
     * @param  string $font 字体文件(ttf)
     * @return boolean
     */
    public function addText($text, $x = 10, $y = 20, $color = '#000000', $size = 12, $angle = 0, $font = null) {
        if (!$font || !is_file($font)) {
            $font = ROOT_PATH . '/framework/include/Image/verdana.ttf';
        }

        $color = $this->_getColor($color);

        if ('ttf' == strtolower(substr($font, -3))) {
            ImageTTFText($this->_imageHandle, $size, $angle, $x, $y, $color, $font, $text);
        } else {
            ImagePSText($this->_imageHandle, $size, $angle, $x, $y, $color, $font, $text);
        }

        return true;
    }

    /**
     * rotate
     * 旋转图像(顺时针方向)
     * 
     * @param  integer $angle 角度(1-360)
     * @param  string $maskColor 旋转后露出的底色(十六进制，例如#000000)
     * @return boolean
     */
    public function rotate($angle, $maskColor = '#ffffff') {
        if (($angle % 360) == 0) {
            return true;
        }

        $maskColor = $this->_getColor($maskColor);
        $this->_imageHandle = ImageRotate($this->_imageHandle, $angle * -1, $maskColor);
        return true;
    }

    /**
     * crop
     * 裁剪图片
     * 
     * @param  integer $width 新图片的宽度
     * @param  integer $height 新图片的高度
     * @param  integer $x 裁剪起点的X坐标
     * @param  integer $y 裁剪起点的Y坐标
     * @trhows Image_Exception
     * @return boolean
     */
    public function crop($width, $height, $x = 0, $y = 0) {
        $maxX = max($width, $x);
        $maxY = max($height, $y);
        if ($maxX > $this->_width || $maxY > $this->_height) {
            throw new Image_Exception('Invalid position.');
        }

        $newImage = $this->_createBlankImage($width, $height);
        imagecopy($newImage, $this->_imageHandle, 0, 0, $x, $y, $width, $height);

        $this->_imageHandle = $newImage;
        $this->_width = $width;
        $this->_height = $height;

        return true;
    }

    /**
     * thumb
     * 生成缩略图（按原图比例）
     *
     * @param  integer $maxWidth 最大宽度
     * @param  integer $maxHeight 最大高度
     * @trhows Image_Exception
     * @return boolean
     */
    public function thumb($maxWidth, $maxHeight) {
        if ($maxWidth <= 0 || $maxWidth <= 0) {
            throw new Image_Exception('Invalid width or height');
        }

        $x = $this->_width / $maxWidth;
        $y = $this->_height / $maxHeight;

        if ($x <= 1 && $y <= 1) {
            return true;
        } elseif ($x > $y) {
            // 宽度大
            $newWidth = $maxWidth;
            $newHeight = round(($maxWidth / $this->_width) * $this->_height, 0);
        } else {
            // 高度大
            $newWidth = round(($maxHeight / $this->_height) * $this->_width, 0);
            $newHeight = $maxHeight;
        }

        $newImage = $this->_createBlankImage($newWidth, $newHeight);
        imagecopyresampled($newImage, $this->_imageHandle, 0, 0, 0, 0, $newWidth, $newHeight, $this->_width, $this->_height);
        imagedestroy($this->_imageHandle);

        $this->_imageHandle = $newImage;
        $this->_width = $width;
        $this->_height = $height;
    }

    /**
     * addWatermark
     * 给图片加水印
     *
     * @param  string $mage 水印图片地址
     * @param  integer $x 水印左上角位置X坐标
     * @param  integer $y 水印左上角位置Y坐标
     * @trhows Image_Exception
     * @return boolean
     */
    public function addWatermark($image, $x, $y) {
        if(!$image || !is_file($image)) {
            throw new Image_Exception('Water image is not exist');
        }
        list($width, $height, $type) = $this->_getInfo($image);

        if($this->_width < $width || $this->_height < $height) {
            throw new Image_Exception('The watermark image size is larger than source image size.');
        }

        $imageHandle = $this->_createImageHandle($image, $type);
        imagecopy($this->_imageHandle, $imageHandle, $x, $y, 0, 0, $width, $height);
        imagedestroy($imageHandle);

        return true;
    }

    /**
     * getHandle
     * 获取image handle
     * 
     * @return object
     */
    public function getHandle() {
        return $this->_imageHandle;
    }

    /**
     * getSize
     * 获取大小
     *
     * @return array
     */
    public function getSize() {
        return array($this->_width, $this->_height);
    }

    /**
     * getImageType
     * 获取图片类型
     * 
     * @return string
     *  + jpeg
     *  + png
     *  + gif
     */
    public function getImageType() {
        return $this->_type;
    }

    /**
     * save
     * 保存图片
     *
     * @param  string $filename 新图片地址
     * @param  string $type 类型（默认为原图片类型）
     *  + gif
     *  + jpeg
     *  + png
     * @param  integer $quality JPEG/PNG质量
     *  + JPEG: 0-100 (0的质量最差)
     *  + PNG: 0-9 (0的质量最好)
     * @return boolean
     */
    public function save($filename, $type = null, $quality = null) {
        if (!$type) {
            $type = $this->_type;
        }

        $function = 'image' . $type;
        if (!function_exists($function)) {
            throw new Image_Exception('Unrecognize image type');
        }

        if ($type == 'jpeg' || $type == 'png') {
            if (!$quality) {
                if ($type == 'jpeg') {
                    $quality = 100;
                } else if ($type == 'png') {
                    $quality = 0;
                }
            }

            $result = $function($this->_imageHandle, $filename, $quality);
        } else {
            $result = $function($this->_imageHandle, $filename);
        }

        imagedestroy($this->_imageHandle);
        return $result;
    }

    /**
     * _getColor
     * 获取颜色代码
     * 
     * @param  string $color 颜色(十六进制或颜色名称，例如#000000、black)
     * @return integer
     */
    protected function _getColor($color) {
        require_once ROOT_PATH . '/framework/include/Image/ColorsDefs.php';

        if ($colorNames[$color]) {
            list($r, $g, $b) = $colorNames[$color];
        } else if ($color[0] == '#' && strlen($color) == 7) {
            $r = hexdec(substr($color, 1, 2));
            $g = hexdec(substr($color, 3, 2));
            $b = hexdec(substr($color, 5, 2));
        } else {
            throw new Image_Exception('Unrecognize color format');
        }

        return imagecolorresolve($this->_imageHandle, $r, $g, $b);
    }

    /**
     * _getInfo
     * 获取图片信息
     * 
     * @param  string $image 图片文件所在路径
     * @return array
     *  + 宽度
     *  + 高度
     *  + 类型
     */
    protected function _getInfo($image) {
        $data = @getimagesize($image);
        if (!is_array($data)) {
            throw new Image_Exception('Cannot fetch image details');
        }

        $map = array(
                     1 => 'gif',
                     2 => 'jpeg',
                     3 => 'png',
                     4 => 'swf',
                     5 => 'psd',
                     6 => 'bmp',
                     7 => 'tiff',
                     8 => 'tiff',
                     9 => 'jpc',
                     10 => 'jp2',
                     11 => 'jpx',
                     12 => 'jb2',
                     13 => 'swc',
                     14 => 'iff',
                     15 => 'wbmp',
                     16 => 'xbm'
                    );
        $type = $map[$data[2]];
        if (!$type) {
            throw new Image_Exception('Unknown image type');
        }

        return array($data[0], $data[1], $type);
    }

    /**
     * _isSupportType
     * 检查是否是支持的图片类型
     * 
     * @param  string $type
     * @return boolean
     */
    protected function _isSupportType($type) {
        $supportTypes = array('gif', 'jpeg', 'png');
        return in_array(strtolower($type), $supportTypes);
    }

    /**
     * _createBlankImage
     * 创建一个空白图像
     * 
     * @param  integer $width 宽度
     * @param  integer $height 高度
     * @return image resource identifier
     */
    protected function _createBlankImage($width, $height) {
        $image = ImageCreateTrueColor($width, $height);
        imagealphablending($image, false);
        imagesavealpha($image, true);
        return $image;
    }

    /**
     * _createImageHandle
     * 从文件创建一个新的图像
     *
     * @param  $image 图片文件地址
     * @param  mixed $type 文件类型
     * @return image resource identifier
     */
    protected function _createImageHandle($image, $type) {
        $function = 'imagecreatefrom' . $type;
        if (!function_exists($function)) {
            throw new Image_Exception($function . ' is not exists.');
        }
        return $function($image);
    }

}
